package com.br.egaragens.controles;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;

import android.content.Context;
import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper;
import com.j256.ormlite.dao.Dao;
import com.j256.ormlite.misc.TransactionManager;
import com.j256.ormlite.stmt.UpdateBuilder;

public abstract class Controller<T, V> {

	protected Dao<T, V> dao;
	protected Context context;
	protected OrmLiteSqliteOpenHelper helper;

	private ArrayList<T> entidades = new ArrayList<T>();
	private int objetos = 0;

	public List<T> getAll() {
		try {
			return dao.queryForAll();
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			dao.clearObjectCache();
		}

		return null;
	}

	public boolean atualizar(T data) {
		try {
			dao.update(data);
			return true;
		}catch(SQLException e) {
			e.printStackTrace();
			return false;
		}
	}

	public boolean inserir(T data) {
		try {
			dao.createOrUpdate(data);
			return true;
		} catch (SQLException e) {
			e.printStackTrace();
			return false;
		} finally {
			dao.clearObjectCache();
		}
	}

	public void refresh(T data) {
		try {
			dao.refresh(data);
		} catch (SQLException e) {

			e.printStackTrace();
		} finally {
			dao.clearObjectCache();
		}
	}

	public T getPeloId(V id) {
		T entidade = null;

		try {
			entidade = dao.queryForId(id);
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			dao.clearObjectCache();
		}

		return entidade;
	}

	public long count() {
		long count = 0;

		try {
			count = dao.countOf();
		} catch (SQLException e) {

			e.printStackTrace();
		} finally {
			dao.clearObjectCache();
		}

		return count;
	}

	public Dao<T, V> getDao() {
		return dao;
	}

	public List<T> getEntidades(Map<String, Object> fields) {
		try {
			return dao.queryForFieldValues(fields);
		} catch (SQLException e) {

			e.printStackTrace();
			return null;
		} finally {
			dao.clearObjectCache();
		}
	}

	public void remove(T entidade) {
		try {
			dao.delete(entidade);
		}catch(SQLException e) {
			e.printStackTrace();
		}
	}

	public boolean criar(T entidade) {
		try {
			dao.create(entidade);
			return true;
		}catch(SQLException e) {
			e.printStackTrace();
			return false;
		}
	}

	public void inserirNoBanco(T entidade) {
		objetos++;
		entidades.add(entidade);

		if(objetos >= 1000) {
			executar();
		}
	}
	
	public void inserirNoBancoPromocao(T entidade) {
		objetos++;
		entidades.add(entidade);

		if(objetos >= 30000) {
			executar();
		}
	}

	public void atualiza(final List<UpdateBuilder<T, V>> lValue){
		try {
			TransactionManager.callInTransaction(helper.getConnectionSource(), new Callable<Void>() {

				public Void call() throws Exception {
					for(UpdateBuilder<T,V> uB  : lValue) {
						try {
							dao.update(uB.prepare());
						}catch(SQLException e) {
							e.printStackTrace();
						}
					}
					return null;
				}
			});
		} catch (SQLException e) {
			e.printStackTrace();
		}finally {

		}
	}

	public void executar() {
		try {
			TransactionManager.callInTransaction(helper.getConnectionSource(), new Callable<Void>() {

				public Void call() throws Exception {
					int x;
					for(T entidade : entidades) {
						try {
							if(entidade == null)
								 x = 0;
							dao.create(entidade);
						}catch(SQLException e) {

						}
					}
					return null;
				}
			});
		} catch (SQLException e) {
			e.printStackTrace();
		}finally {
			objetos = 0;
			entidades = new ArrayList<T>();
		}
	}
}
